/**
 * @fileOverview Castle游戏实例类源文件
 * @author <a href="http://sivory.my.phpcloud.com">Sivory</a>
 * @version 0.0.1
 */

(function() {

	/** @exports _Class as Name.Sivory.Castle.Core.Game */
	var _Class =

	/**
	 * @class Castle游戏实例类Game。它托管着一个游戏集成环境，保证游戏各部件的协同工作。游戏的主循环在此类中托管，另外，Game还负责游戏不同界面间的切换。
	 * @param {Name.Sivory.Castle.Core.Config} config 游戏实例配置参数对象，参见{@link Name.Sivory.Castle.Core.Config}
	 * @author <a href="http://sivory.my.phpcloud.com">Sivory</a>
	 * @version 0.0.1
	 */
	Name.Sivory.Castle.Core.Game = function(config) {

			/**
			 * @public
			 * @field
			 * @constant
			 * @type String
			 * @description 游戏内核版本
			 * @since 0.0.1
			 */
			this.V = "0.0.1";

			/**
			 * @public
			 * @field
			 * @type Name.Sivory.Castle.Core.Config
			 * @description 游戏内核配置对象
			 * @since 0.0.1
			 */
			this.config = new Name.Sivory.Castle.Core.Config();

			/**
			 * @public
			 * @field
			 * @type Name.Sivory.Castle.Core.Stage
			 * @description 游戏渲染器
			 * @since 0.0.1
			 */
			this.stage = new Name.Sivory.Castle.Core.Stage(this);

			/**
			 * @public
			 * @field
			 * @type Name.Sivory.Castle.Core.Studio
			 * @description 游戏音效管理器
			 * @since 0.0.1
			 */
			this.studio = new Name.Sivory.Castle.Core.Studio(this);

			/**
			 * @public
			 * @field
			 * @type Name.Sivory.Castle.Core.Status
			 * @description 游戏状态机
			 * @since 0.0.1
			 */
			this.status = new Name.Sivory.Castle.Core.Status(this);

			/**
			 * @public
			 * @field
			 * @type Name.Sivory.Castle.Core.Controller
			 * @description 游戏控制器
			 * @since 0.0.1
			 */
			this.controller = new Name.Sivory.Castle.Core.Controller(this);

			/**
			 * @public
			 * @field
			 * @type Name.Sivory.Castle.Core.Source
			 * @description 游戏源码托管
			 * @since 0.0.1
			 */
			this.source = new Name.Sivory.Castle.Core.Source();

			/**
			 * @public
			 * @field
			 * @type Name.Sivory.Castle.Core.Resource
			 * @description 游戏资源集合
			 * @since 0.0.1
			 */
			this.resource = new Name.Sivory.Castle.Core.Resource();

			/**
			 * @public
			 * @field
			 * @type Name.Sivory.Castle.Core.Debug
			 * @description 游戏实例的调试单元
			 * @since 0.0.1
			 */
			this.debug = new Name.Sivory.Castle.Core.Debug(this);

			/**
			 * @public
			 * @field
			 * @type Name.Sivory.Castle.Core.Loader
			 * @description 游戏加载数据的画面
			 * @since 0.0.1
			 */
			this.loader = new Name.Sivory.Castle.Core.Loader(this);

			/**
			 * @public
			 * @field
			 * @type Number
			 * @description 游戏帧计数器
			 * @since 0.0.1
			 */
			this.frameCount = 0;

			/**
			 * @public
			 * @field
			 * @type Number
			 * @description 游戏开始时间
			 * @since 0.0.1
			 */
			this.startTime = 0;

			/**
			 * @private
			 * @field
			 * @type Object
			 * @description 内核运行前需要准备好的模块
			 * source 游戏源模块
			 * canvas 游戏渲染模块
			 * start 用户启动开关
			 * @since 0.0.1
			 */
			this.readyList = {
				source: false,
				canvas: false,
				start: false
			};

			/**
			 * @public
			 * @field
			 * @type Name.Sivory.Castle.Util.Hook
			 * @description 主循环中循环体开始时将被执行的钩子
			 * @since 0.0.1
			 */
			this.frameBeginHook = new Name.Sivory.Castle.Util.Hook();

			/**
			 * @public
			 * @field
			 * @type Name.Sivory.Castle.Util.Hook
			 * @description 主循环中循环体结束时将被执行的钩子
			 * @since 0.0.1
			 */
			this.frameEndHook = new Name.Sivory.Castle.Util.Hook();

			/**
			 * @private
			 * @field
			 * @type Boolean
			 * @description 用于控制游戏主循环执行的开关
			 * @since 0.0.1
			 */
			this.loopStoped = true;

		};

	/**
	 * @public
	 * @function
	 * @description 启动游戏
	 * @since 0.0.1
	 */
	_Class.prototype.start = function() {
		this.startTime = new Date().getTime();
		this.ready("start");
	};

	/**
	 * @private
	 * @function
	 * @description 游戏内核初始化
	 * @since 0.0.1
	 */
	_CLass.prototype.init = function(config) {
		//检测浏览器类型
		this.checkAgent();
		//构建游戏配置参数
		this.config.combine(config);
		var onXmlDone = function() {
				this.ready("source");
			};
		//读取资源
		this.source.load(this.config.resource, 'json', onXmlDone);
	};

	/**
	 * @private
	 * @function
	 * @description 检测浏览器的类型
	 * @since 0.0.1
	 */
	_Class.prototype.checkAgent = function() {
		var agentString = navigator.userAgent.toLowerCase();
		//先把Chrome挑出来，因为Chrome也有Safari的特征。
		if(agentString.indexOf("chrome") > -1) {
			this.userAgent = "C";
			this.requestAnimationFrame = window.webkitRequestAnimationFrame;
		} else if(agentString.indexOf("firefox") > -1) {
			this.userAgent = "F";
			this.requestAnimationFrame = window.mozRequestAnimationFrame;
		} else if(agentString.indexOf("safari") > -1) {
			this.userAgent = "S";
			this.requestAnimationFrame = window.webkitRequestAnimationFrame;
		} else if(agentString.indexOf("opera") > -1) {
			this.userAgent = "O";
			this.requestAnimationFrame = window.oRequestAnimationFrame;
		} else if(agentString.indexOf("msie 9") > -1 || agentString.indexOf("msie 10") > -1) {
			this.userAgent = "I";
			this.requestAnimationFrame = window.msRequestAnimationFrame;
		} else {
			throw "Castle不支持当前浏览器";
		};
	};

	/**
	 * @public
	 * @function
	 * @description 当游戏中的某个模块准备好时，调用此函数告知内核相应模块已准备好。
	 * @param {String} key 已准备好的模块的名称
	 * @since 0.0.1
	 */
	_Class.prototype.ready = function(key) {
		if(this.readyList[key] === null || this.readyList[key] === undefined) return;
		this.readyList[key] = true;
		var allReady = true;
		//检测全部模块是否都已就绪
		for(index in this.readyList) {
			allReady = allReady && this.readyList[index];
			if(!allReady) break;
		};
		if(allReady) {
			//新建一个入口界面
			var entry = new OS_Menu(this, this.config.entryInterface);
			this.loader.start();
			entry.show();
			OS_Resource.loadResource(this, this.loader, function() {
				this.loader.stop();
				entry.playBGM();
				this.mainLoop();
			});
		};
	};

	/**
	 * @public
	 * @function
	 * @description 执行游戏的主循环
	 * @since 0.0.1
	 */
	_Class.prototype.runMainLoop=function()
	{
		//开启循环
		this.loopStoped = false;
		//执行游戏主循环
		this.mainLoop();
	}

	/**
	 * @public
	 * @function
	 * @description 终止游戏的主循环
	 * @since 0.0.1
	 */
	 _Class.prototype.stopMainLoop=function()
	 {
	 	//停止循环
	 	this.loopStoped=true;
	 }

	/**
	 * @private
	 * @function
	 * @description 游戏主循环的循环体
	 * @since 0.0.1
	 */
	_Class.prototype.mainLoop = function() {

		try {
			this.frameCount++;

			//执行循环体开始位置的钩子
			this.frameBeginHook.run();

			//开始记录循环体(帧)的调试信息
			this.debug.start();

			//更新处于活动状态中的界面
			this.status.activeInterface.refresh();

			//结束记录循环体(帧)的调试信息
			this.debug.finish();

			//执行循环体结束位置的钩子
			this.frameEndHook.run();

			//若主循环在正常执行，则请求执行主循环的下一个循环体
			if(!loopStoped) {
				this.requestAnimationFrame(mainLoop);
			}

		} catch(err) {
			//停止主循环的执行
			this.loopStoped = true;
			
			//触发错误事件
			if(typeof this.onError === "function") {
				this.onError(err);
			}
		}

	};

	/**
	 * @private
	 * @function
	 * @description 安排一个动画级别的延迟执行循环体，此延迟一般由浏览器分配。
	 * @param {Function} func 循环体函数
	 * @since 0.0.1
	 */
	_Class.prototype.requestAnimationFrame = function(func) {
		throw "Castle不支持当前浏览器";
	};

	/**
	 * @public
	 * @event
	 * @description 当游戏运行出错时触发此事件
	 * @param {Name.Sivory.Castle.Core.Game} game 游戏实例
	 * @param {String} err 错误信息
	 * @since 0.0.1
	 */
	_Class.prototype.onError = function(game, err) {
		//do nothing...
	};

})();